package com.sjw.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sjw.data.constant.EsConstant;
import com.sjw.entity.Account;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.Sum;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/es")
@Slf4j
public class TestController {

    @Autowired
    private RestHighLevelClient client;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;

    private final ObjectMapper objectMapper = new ObjectMapper();

    @GetMapping("/test")
    public String testEs(){
        try {
            boolean ping = client.ping(RequestOptions.DEFAULT);
            return ping ? "连接成功":"连接失败";
        }catch (IOException e){
            return "失败："+e.getMessage();
        }
    }
    @GetMapping("/test1")
    public List<Account> testEs1(){
        List<Account> accounts = new ArrayList<>();
        try {
            //1.准备request
            SearchRequest request = new SearchRequest(EsConstant.ES_ACCOUNTS);
            //2.准备请求参数
            request.source().query(QueryBuilders.matchAllQuery());
            //3.执行查询
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);

            //4.处理相应并将结果添加到列表
            for (SearchHit hit : response.getHits().getHits()) {
                Account account = objectMapper.convertValue(hit.getSourceAsMap(), Account.class);
                accounts.add(account);
            }
        }catch (Exception e){
            log.info("失败：{}",e.getMessage());
        }
        return accounts;
    }

    /**
     * 获取账户的总余额
     * @return
     */
    @GetMapping("/test2")
    public double testEs2(){
        try {
            SearchRequest request = new SearchRequest(EsConstant.ES_ACCOUNTS);
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

            //聚合计算总余额
            sourceBuilder.aggregation(AggregationBuilders.sum("total_balance").field("balance"));
            request.source(sourceBuilder);

            SearchResponse response = client.search(request,RequestOptions.DEFAULT);
            Sum totalBalance = response.getAggregations().get("total_balance");

            return totalBalance.getValue();

        }catch (Exception e){
            log.info("失败：{}",e.getMessage());
        }
        return 0;
    }

    /**
     * 按城市统计账户数量
     * @return
     */
    @GetMapping("/test3")
    public void testEs3(){
        try {
            SearchRequest request = new SearchRequest(EsConstant.ES_ACCOUNTS);
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

            //按城市聚合
            sourceBuilder.aggregation(AggregationBuilders.terms("accounts_by_city").field("city"));
            request.source(sourceBuilder);

            SearchResponse response = client.search(request,RequestOptions.DEFAULT);
            Terms terms = response.getAggregations().get("accounts_by_city");

            for (Terms.Bucket bucket : terms.getBuckets()) {
                System.out.println("City:"+bucket.getKey() + ",Count:"+bucket.getDocCount());
            }

        }catch (Exception e){
            log.info("失败：{}",e.getMessage());
        }
    }

    /**
     * 获取每个雇主的平均余额
     * @return
     */
    @GetMapping("/test4")
    public void testEs4(){
        try {
            SearchRequest request = new SearchRequest(EsConstant.ES_ACCOUNTS);
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

            //按城市聚合
            sourceBuilder.aggregation(AggregationBuilders.avg("accounts_by_city").field("city"));
            request.source(sourceBuilder);

            SearchResponse response = client.search(request,RequestOptions.DEFAULT);
            Terms terms = response.getAggregations().get("accounts_by_city");

            for (Terms.Bucket bucket : terms.getBuckets()) {
                System.out.println("City:"+bucket.getKey() + ",Count:"+bucket.getDocCount());
            }

        }catch (Exception e){
            log.info("失败：{}",e.getMessage());
        }
    }
}
